package com.zch.threadpool.mythreadpool;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 我自己的线程池
 */
public class MyThreadPool {
    private int coreCount;//核心线程数
    private int maxCount; //最大线程数
    private long keepAliveTime; //线程有效存活时间
    private TimeUnit unit; //存活时间的单位
    private boolean start = true;
    private boolean end;
    private BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
    // 线程池里可用的线程
    public static LinkedBlockingQueue<WorkThread> availableThreads = new LinkedBlockingQueue<WorkThread>();// 用来保存创建自定义的Thread这里最好使用阻塞式队列因为你添加和移除是在不同线程中操作

    public MyThreadPool(int coreCount, int maxCount, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> taskQueue) {
        super();
        this.coreCount = coreCount;
        this.maxCount = maxCount;
        this.keepAliveTime = keepAliveTime;
        this.unit = unit;
        this.taskQueue=taskQueue;

        // 创造核心数目线程数量
        for (int i = 0; i < coreCount; i++) {
            availableThreads.add(new WorkThread());
        }
        /**
         * 不停的轮询 任务队列，如果任务队列有待处理的任务，并且可用的线程队列里有可用的线程，则会从任务队列里取任务执行。
         */
        while(true){
            if (taskQueue.size() > 0 && availableThreads.size() > 0) {//如果任务队列不为空并且线程队列也不为空
                WorkThread thread = availableThreads.remove();//从线程阻塞队列中获取一个线程来执行任务
                thread.setRunnable(taskQueue.remove());
            }
        }
    }

    // 提供给外面用，提交待执行的任务
    public void execute(Runnable runnable) {
      /*  if (start) {
            runInQueueTask();
            start = false;
        }*/
        if (availableThreads.size() > 0) {// 如果还有线程空闲就直接执行
            runTask(runnable);
        } else {
            taskQueue.add(runnable);// 添加到任务队列
        }
    }

   /* private void runInQueueTask() {//这个方法主要是用来开启一个线程来不断扫描任务队列中是否有任务
        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {//这里让它不断扫描
                    if (end)//如果结受到结束标记就结束
                        break;
                    if (taskQueue.size() > 0 && availableThreads.size() > 0) {//如果任务队列不为空并且线程队列也不为空
                        WorkThread thread = availableThreads.remove();//从线程阻塞队列中获取一个线程来执行任务
                        thread.setRunnable(taskQueue.remove());
                    } else {
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
*/
    private void runTask(Runnable runnable) {
        //从队列里取一个线程
        WorkThread thread = availableThreads.remove();// 从线程列中获取空余线程

        thread.setRunnable(runnable);// 设置任务到线程上
        if (thread.first)// 如果是第一次执行启动start方法
            thread.start();
    }

    public void shutDown() {//关闭线程池中所有的资源来停止运行
        while (true) {
            if (availableThreads.size() == coreCount&&taskQueue.size()==0) {//只有当任务执行完才关闭它们
                end = true;// 修改标记使扫描任务队列的线程停止
                for (WorkThread thread : availableThreads) {// 循环关闭每个线程及让它的start方法执行完
                    thread.closeThread();
                }
                break;
            }else{
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
            }
        }
    }
}
